#pragma once
#include "CFrameworkElement.h"
#include "CMILMatrix.h"


class CPopupRoot;

class CPopup :
	public CFrameworkElement
{

private: 
	CPopup(CCoreServices * pCore);
	void RaisePopupEvent(XUINT32 eventId);
	HRESULT AddChildAsNamescopeOwner();
	HRESULT RemoveChildAsNamescopeOwner();
	XBOOL ShouldRemoveChildAsNamescopeOwner();
	HRESULT Open();
	HRESULT Close();
	HRESULT SetChild(CUIElement * pChild);
	HRESULT RemoveChild();
protected: 
	virtual HRESULT EnterImpl(CDependencyObject * pNamescopeOwner, struct EnterParams params);
	virtual HRESULT LeaveImpl(CDependencyObject * pNamescopeOwner, struct LeaveParams params);
	virtual HRESULT OnKeyUp(struct Xcp_IDependencyObject * pEventArgs);
	virtual HRESULT OnKeyDown(struct Xcp_IDependencyObject * pEventArgs);
public: 
	virtual ~CPopup();
	static HRESULT Create(CDependencyObject * * ppObject, CREATEPARAMETERS * pCreate);
	virtual XUINT32 GetTypeIndex() const;
	virtual HRESULT SetValue(CDependencyProperty * pdp, CValue * pValue);
	virtual HRESULT ClearValue(CDependencyProperty * pdp);
	HRESULT GetAssociatedPopupRoot(CPopupRoot * * ppAssociatedPopupRoot);
	static HRESULT Child(struct Xcp_IDependencyObject * pObject, XUINT32 cArgs, CValue * pArgs, CValue * pResult);
	virtual HRESULT AddEventListener(CDependencyProperty * pdp, CValue * pValue, XINT32 iListenerType, CValue * pResult, XINT32 fHandledEventsToo);
	virtual HRESULT RemoveEventListener(CDependencyProperty * pdp, CValue * pValue);
	virtual XUINT32 Release();
	void AsyncRelease();
	XBOOL IsOpen();
	virtual HRESULT UpdateImplicitStyle(CStyle * pOldStyle, CStyle * pNewStyle, XBOOL bForceUpdate, XBOOL bUpdateChildren, XBOOL isLeavingParentStyle);
	HRESULT NWRenderPopup(const struct SharedRenderParams & sharedRP, const struct NWRenderParams & nwRP);
	static CPopup * GetClosestPopupAncestor(CUIElement * pChild);
	virtual XBOOL IsFocusable();
protected: 
	virtual XBOOL NWSkipRendering();
	virtual HRESULT PreChildrenPrintVirtual(const struct SharedRenderParams & sharedPrintParams, const struct D2DPrecomputeParams & cp, const struct D2DRenderParams & printParams);
	virtual HRESULT MarkInheritedPropertyDirty(CDependencyProperty * pdp, CValue * pValue);
	virtual void NWPropagateDirtyFlag(enum DirtyFlags::Value flags);
	virtual HRESULT BoundsTestInternal(const HitTestPolygon & target, struct IBoundsTestCallback * pCallback, enum BoundsWalkHitResult::Value * pResult);
	virtual HRESULT BoundsTestInternal(const struct XPOINTF & target, struct IBoundsTestCallback * pCallback, enum BoundsWalkHitResult::Value * pResult);
	virtual HRESULT BoundsTestChildren(const HitTestPolygon & target, struct IBoundsTestCallback * pCallback, enum BoundsWalkHitResult::Value * pResult);
	virtual HRESULT BoundsTestChildren(const struct XPOINTF & target, struct IBoundsTestCallback * pCallback, enum BoundsWalkHitResult::Value * pResult);
	virtual HRESULT GenerateChildOuterBounds(struct XRECTF_RB * pBounds);
	virtual XUINT32 IgnoresInheritedClips();
private: 
	virtual HRESULT LeavePCSceneSubgraph();
	virtual CUIElement * GetCompositionPathParent();
	void MarkCompositionPath();
	void UnmarkCompositionPath();
	HRESULT NWPreRender();
	HRESULT NWRenderPopupProjection(CCompositeVectorBuffer * pIntermediateVectorBuffer, CFrameVectorBuffer * pTargetVectorBuffer, struct PopupParentProjectionData * pPopupParentProjectionData);
public: 
	CUIElement * m_pChild;
	XFLOAT m_eHOffset;
	XFLOAT m_eVOffset;
	XBOOL m_fIsOpen;
	XBOOL m_fIsLightDismissEnabled;
	XBOOL m_fIsLightDismiss;
	CTransitionCollection * m_pChildTransitions;
	XBOOL m_fAsyncQueueOnRelease:1;
private: 
	XBOOL m_fNWNeedsTransformToRootUpdate:1;
	XBOOL m_fNWTransformToSurfaceChanged:1;
	XBOOL m_fNWProjectionsToRootChanged:1;
	XBOOL m_fRemovingListeners:1;
	XBOOL m_fMadeChildNamescopeOwner:1;
	XBOOL m_fNWAreAllAncestorsVisible:1;
	XBOOL m_fIsPrintDirty:1;
	XBOOL m_wasMarkedAsRedirectionElementOnEnter:1;
	XBOOL m_wasMarkedAsRedirectionElementOnOpen:1;
	XUINT32 m_cEventListenerCount;
	struct ITransformer * m_pTransformer;

	xvector<PopupParentProjectionData *> m_parentProjectionData;

	CMILMatrix m_popupToSurfaceTransform;

	CWeakRef * m_pPreviousFocusWeakRef;
	enum FocusState m_focusStateAfterClosing;
};